package com.eerl.pdev.gen;

import com.eerl.pdev.MySettingsState;
import com.eerl.pdev.util.Notice;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindowManager;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@SuppressWarnings("unused")
public class GenEmptyTemplate extends AnAction {

    private static final String NULL_STRING = "20240920210843NULLxlletools";
    private static final char SINGLE_CLOSE_TAG = ':';

    private static final String SHOW_PANEL_ID = "ShowGenTemplateFileInteractivePanel";

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        assert project != null;
        MyToolWindowFactory.setAnEvent(e);
        // 这里创建后我会在MyToolsWIndContent内部做一些事，但是需要AnActionEvent
        Objects.requireNonNull(ToolWindowManager.getInstance(project).getToolWindow(SHOW_PANEL_ID)).show();
    }

    public static void gen(Map<String, String> vars, AnActionEvent event) {
        try {
            final String SRC_PATH = MySettingsState.getInstance().PROJECT_ERL_SRC_ABS_PATH;
            final String TOOLS_PATH = MySettingsState.getInstance().PROJECT_ERL_TOOLS_ABS_PATH;
            if (SRC_PATH.isEmpty() || TOOLS_PATH.isEmpty()) {
                throw new RuntimeException("in setting, SRC_PATH or TOOLS_PATH is empty");
            }

            String mod = vars.getOrDefault(MyToolWindowFactory.VAR_KEY_MOD, NULL_STRING);
            checkReplaceVarsExist("gen_mod_extract", mod);
            final String HRL_PATH = SRC_PATH + "../include/" + mod + ".hrl";
            final String HRL_NOTICE_PATH = "../include/notice/" + mod + ".hrl";
            final String MOD_PATH = "./mod/" + mod;
            final String DATA_PATH = TOOLS_PATH + "./gen_data/cfg/";

            final String GEN_TEMPLATE_ROOT_PATH = MySettingsState.getInstance().GEN_TEMPLATE_ABS_ROOT_PATH;

            final String HRL_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "hrl.template";
            final String NOTICE_HRL_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "notice_hrl.template";
            final String ROLE_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "role.template";
            final String LIB_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "lib.template";
            final String RPC_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "rpc.template";
            final String DATA_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "data.template";
            final String VER_TEMPLATE_FILE_PATH = GEN_TEMPLATE_ROOT_PATH + "ver.template";

            genTemplate(HRL_TEMPLATE_FILE_PATH, HRL_PATH, vars, event);
            genTemplate(NOTICE_HRL_TEMPLATE_FILE_PATH, HRL_NOTICE_PATH, vars, event);
            genTemplate(ROLE_TEMPLATE_FILE_PATH, MOD_PATH + "_role.erl", vars, event);
            genTemplate(LIB_TEMPLATE_FILE_PATH, MOD_PATH + "_lib.erl", vars, event);
            genTemplate(RPC_TEMPLATE_FILE_PATH, MOD_PATH + "_rpc.erl", vars, event);
            genTemplate(DATA_TEMPLATE_FILE_PATH, MOD_PATH + "_data.erl", vars, event);
            genTemplate(VER_TEMPLATE_FILE_PATH, MOD_PATH + "_ver.erl", vars, event);
        } catch (Exception e) {
            String message = e.getMessage() + "\n e => \n" + e;
            Notice.showNotification(event, message, NotificationType.ERROR);
        }


    }

    public void testGenTemplate(String path) {
        File file = new File(path);
        System.out.println(file.getAbsoluteFile());
        File outFile = new File("./aa2");
        Map<String, String> vars = new HashMap<>();
        vars.put("name", "xll");
        vars.put("var", "vvvvvaaaaa");
        vars.put("date", "20240920");
        vars.put("mod", "camp_custom");
        try {
            fileParseAndReplace(file, outFile, vars);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void genTemplate(String templatePath, String outPath, Map<String, String> vars, AnActionEvent event) throws Exception {
        File templateFile = new File(templatePath);
        File outFile = new File(outPath);
        fileParseAndReplace(templateFile, outFile, vars);
        Notice.showNotification(event, "file gen in: " + outFile.getAbsolutePath(), NotificationType.INFORMATION);
    }

    private static void fileParseAndReplace(File Templatefile, File outFile, Map<String, String> vars) throws Exception {
        /*
        test:
        :=>d
        ::::
        :::
        ::var::
        ::date::
        ::mod::
        ::name::
        ::na:me::
        :name::
        name::
        ::name:
        :name


         */
        FileInputStream in = new FileInputStream(Templatefile);
        FileOutputStream out = new FileOutputStream(outFile);

        final int closeTagVal = 2;
        int closeTagLeftVal = 0;
        int closeTagRightVal = 0;

        // 读取字符串
        StringBuilder builder = new StringBuilder();
        // 写入最后文件的字符串构建
        StringBuilder outBuilder = new StringBuilder();
        // 变量字符串构建
        StringBuilder varBuilder = new StringBuilder();

        int len;
        byte[] buf = new byte[1024];
        while ((len = in.read(buf)) != -1) {
            // 变量闭合标识: ::var::
            char[] chars = new String(buf, 0, len).toCharArray();
            // :::
            for (char aChar : chars) {

                boolean close_tag_continue = false;
                builder.append(aChar);
                if (aChar == SINGLE_CLOSE_TAG && closeTagLeftVal >= closeTagVal) {
                    // 右匹配过程
                    closeTagRightVal++;
                    close_tag_continue = true;
                } else if (aChar == SINGLE_CLOSE_TAG) {
                    // 左匹配过程
                    closeTagLeftVal++;
                    close_tag_continue = true;
                }

                if (closeTagLeftVal == closeTagVal && closeTagRightVal == closeTagVal) {
                    // 双端闭合 判定为预插入变量 进行变量替换
                    String varName = varBuilder.toString().trim();
                    if (varName.isBlank()) {
                        // 匹配崩溃
                        // 初始化匹配
                        closeTagLeftVal = 0;
                        closeTagRightVal = 0;
                        varBuilder = varBuilder.isEmpty() ? varBuilder : new StringBuilder();
                        // 写入
                        outBuilder.append(builder);
                        builder = builder.isEmpty() ? builder : new StringBuilder();
                        continue;
                    }
                    String varVal = vars.getOrDefault(varName, NULL_STRING);
                    checkReplaceVarsExist(varName, varVal);
                    // 写入
                    outBuilder.append(varVal);
                    // 重置
                    closeTagLeftVal = 0;
                    closeTagRightVal = 0;
                    varBuilder = new StringBuilder();
                    builder = new StringBuilder();
                } else if (closeTagLeftVal == closeTagVal && closeTagRightVal == 0) {
                    // 只有左闭合
                    if (aChar != SINGLE_CLOSE_TAG) {
                        varBuilder.append(aChar);
                    }
                } else if (!close_tag_continue) {
                    // 匹配崩溃
                    // 初始化匹配
                    closeTagLeftVal = 0;
                    closeTagRightVal = 0;
                    varBuilder = varBuilder.isEmpty() ? varBuilder : new StringBuilder();
                    // 写入
                    outBuilder.append(builder);
                    builder = builder.isEmpty() ? builder : new StringBuilder();
                }

            }
        }
        out.write(outBuilder.toString().getBytes());
        in.close();
        out.close();
    }

    // 检查确保需要替换的值存在
    private static void checkReplaceVarsExist(String varName, String var) {
        if (var.equals(NULL_STRING)) {
            throw new RuntimeException("unexpected null var[" + varName + "]");
        }
    }

    private static String nchar(int n, char ch) {
        return String.valueOf(ch).repeat(n);
    }
}
